package com.cn.lp.jpa.cq.domain;

import com.cn.lp.jpa.cq.CQLogicalType;
import com.cn.lp.jpa.cq.CQOrderType;
import com.cn.lp.jpa.cq.utils.JSONAide;
import com.google.common.base.Joiner;

import java.util.*;

/**
 * 标记
 *
 * @author wqr
 * Created by on 2019/8/7
 */
public class CQSign {

    /**
     * 数据源类型
     */
    private Class<?> fromClass;

    private List<CQSignItem> itemList = new ArrayList<>();

    private List<CQOrderSign> orderList = new ArrayList<>();

    public CQSign(Class<?> fromClass) {
        this.fromClass = fromClass;
    }

    public void markOrder(CQField field, CQOrderType orderType) {
        orderList.add(CQOrderSign.of(field, orderType));
    }

    public void markBlock(CQLogicalType logicalType, boolean non, boolean start) {
        itemList.add(CQBlockSign.of(logicalType, non, start));
    }

    public void markCondition(CQLogicalType logicalType, boolean non, String condition, CQField field) {
        itemList.add(CQConditionSign.of(logicalType, (non ? "!" : "") +condition + "#F(" + field.getName() + ")"));
    }

    public void markCondition(CQLogicalType logicalType, boolean non, String condition, CQField field1, CQField field2) {
        itemList.add(CQConditionSign.of(logicalType, (non ? "!" : "") +condition + "#F(" + field1.getName() + "):F(" + field2.getName() + ")"));
    }

    public void markCondition(CQLogicalType logicalType, boolean non, String condition, CQField field1, Object data) {
        itemList.add(CQConditionSign.of(logicalType, (non ? "!" : "") + condition + "#F(" + field1.getName() + "):" + JSONAide.toJson(data)));
    }

    public void markBetween(CQLogicalType logicalType, boolean non, CQField field, Object data1, Object data2) {
        itemList.add(CQConditionSign.of(logicalType, (non ? "!" : "") +"between#F(" + field.getName() + "):" + JSONAide.toJson(data1) + "-" + JSONAide.toJson(data2)));
    }

    private String createBlock(Deque<CQSignItem> dataList) {
        CQSignItem item = dataList.pollFirst();
        List<String> blockList = new ArrayList<>();
        while (item != null) {
            if (item instanceof CQBlockSign) {
                if (((CQBlockSign) item).isStart()) {
                    String block = createBlock(dataList);
                    if (block != null) {
                        block = (((CQBlockSign) item).isNon() ? "!" : "") + block;
                        blockList.add(block);
                    }
                } else {
                    if (blockList.size() > 1) {
                        Collections.sort(blockList);
                        StringBuilder sb = new StringBuilder();
                        sb.append("|");
                        sb.append(Joiner.on("-").join(blockList));
                        sb.append("|");
                        return sb.toString();
                    } else if (blockList.size() == 1) {
                        return blockList.get(0);
                    } else {
                        return null;
                    }
                }
            } else {
                blockList.add(item.getLogicalType() + "^" + item.getText());
            }
            item = dataList.pollFirst();
        }
        Collections.sort(blockList);
        return Joiner.on("-").join(blockList);
    }

    public String createSign() {
        LinkedList<CQSignItem> itemList = new LinkedList<>(this.itemList);
        CQSignItem item = itemList.pollFirst();
        boolean firstCondition = true;
        List<String> blockList = new ArrayList<>();
        while (item != null) {
            if (item instanceof CQBlockSign) {
                String block = createBlock(itemList);
                if (block != null) {
                    block = (((CQBlockSign) item).isNon() ? "!" : "") + block;
                    blockList.add(block);
                    firstCondition = false;
                }
            } else {
                if(firstCondition) {
                    blockList.add(item.getText());
                    firstCondition = false;
                } else {
                    blockList.add(item.getLogicalType() + "^" + item.getText());
                }

            }
            item = itemList.pollFirst();
        }
        List<String> orderSignList = new ArrayList<>();
        for (CQOrderSign orderSign : orderList) {
            orderSignList.add("F(" + orderSign.getField().getName() + ")*" + orderSign.getOrderType());
        }
        Collections.sort(blockList);
        if (!orderSignList.isEmpty()) {
            Collections.sort(orderSignList);
            blockList.addAll(orderSignList);
        }
        return Joiner.on(",").join(blockList);
    }

}
